import { reactive } from "./reactive.js";

export function ref(val) {
  /* 包装对象，Proxy只能代理非原始值 */
  const wrapper = {
    value: val,
  };

  /* 在 wrapper 对象中定义一个 不可枚举不可修改的 __v_isRef 属性，值为true，代表这是一个ref */
  Object.defineProperty(wrapper, "__v_isRef", {
    value: true,
  });

  return reactive(wrapper);
}

/**
 * @description 将reactive对象中的某个属性转换为ref
 * @param {*} proxy 代理对象
 * @param {*} key 代理对象上的key
 * @returns
 */
export function toRef(proxy, key) {
  /* 包装对象 */
  const wrapper = {
    /* 获取value值，返回响应式对象的属性值 */
    get value() {
      return proxy[key];
    },

    /* 设置value值，设置响应式对象的属性值 */
    set value(newVal) {
      proxy[key] = newVal;
    },
  };

  /* 在 wrapper 对象中定义一个 不可枚举不可修改的 __v_isRef 属性，值为true，代表这是一个ref */
  Object.defineProperty(wrapper, "__v_isRef", {
    value: true,
  });

  return wrapper;
}

/**
 * @description 将reactive对象中的所有属性转换为ref
 * @param {*} proxy 代理对象
 * @returns
 */
export function toRefs(proxy) {
  /* 存储ref化后的键值对 */
  const ret = {};

  for (const key in proxy) {
    ret[key] = toRef(proxy, key);
  }

  return ret;
}

export function proxyRefs(refsObj) {
  return new Proxy(refsObj, {
    get(target, key, receiver) {
      /* 获取key对应的包装对象：
        {
         get value() {
           return proxy[key]
         },
        }
      
      */
      const value = Reflect.get(target, key, receiver);

      /* 如果是ref对象，则返回其value值 */
      return value.__v_isRef ? value.value : value;
    },

    set(target, key, newVal, receiver) {
      /* 获取key对应的包装对象 */
      const value = target[key];

      /* 如果是ref，通过value设置器给响应式对象对应的key设置新的值 */
      if (value.__v_isRef) {
        value.value = newVal;
        return true;
      }

      return Reflect.set(target, key, newVal, receiver);
    },
  });
}
